package com.amap.search.service;

import com.amap.search.entity.es.EsConstant;
import com.amap.search.entity.es.PoiRecordEs;
import com.amap.search.entity.vo.PoiRequest;
import com.amap.search.mapper.es.PoiRecordDao;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.queryparser.xml.builders.BooleanQueryBuilder;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Service
public class ElasticSearchQueryService {

    @Resource
    private PoiRecordDao poiRecordDao;

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;


    public List<PoiRecordEs> queryPoiInfo(PoiRequest request){
        BoolQueryBuilder queryCombo = QueryBuilders.boolQuery();
        /**
         * 拼接查询条件
         */
        if(StringUtils.isNotEmpty(request.getQueryStr())){
            QueryBuilder fuzzyQuery = QueryBuilders.queryStringQuery(request.getQueryStr());
            queryCombo.must(fuzzyQuery);
        }
        if(StringUtils.isNotEmpty(request.getAdCode())) {
            QueryBuilder adQuery = QueryBuilders.termQuery(EsConstant.adCode + EsConstant.keyWord, request.getAdCode());
            queryCombo.must(adQuery);
        }
        if(StringUtils.isNotEmpty(request.getTypeCode())){
            QueryBuilder typeQuery = QueryBuilders.termQuery(EsConstant.typeCode + EsConstant.keyWord, request.getTypeCode());
            queryCombo.must(typeQuery);
        }
        PageRequest page = PageRequest.of(0,10);
        return getEsDateWithoutSort(queryCombo, page, PoiRecordEs.class);
    }

    public List<PoiRecordEs> simpleQuery(String queryStr){
        QueryBuilder queryBuilder = QueryBuilders.queryStringQuery(queryStr);
        PageRequest page = PageRequest.of(0, 10);
        return getEsDateWithoutSort(queryBuilder, page, PoiRecordEs.class);
    }

    public <T> List<T> getEsDateWithSort(QueryBuilder qb, PageRequest pageRequest, Class<T> clazz, String sortField) {
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(qb).withPageable(pageRequest)
                .withSort(SortBuilders.fieldSort(sortField).order(SortOrder.DESC)).build();
        searchQuery.setTrackTotalHits(true);
        return getESDate(searchQuery, clazz);
    }

    private  <T> List<T> getEsDateWithoutSort(QueryBuilder qb, PageRequest pageRequest, Class<T> clazz) {
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(qb).withPageable(pageRequest)
                .build();
        searchQuery.setTrackTotalHits(true);
        return getESDate(searchQuery, clazz);
    }


    private <T> List<T> getESDate(NativeSearchQuery searchQuery,  Class<T> clazz){
        SearchHits<T> search = elasticsearchRestTemplate.search(searchQuery, clazz);
        List<SearchHit<T>> result = search.getSearchHits();
        List<T> list = new ArrayList<>();
        for (SearchHit<T> searchHit : result) {
            list.add(searchHit.getContent());
        }
        return list;
    }
}
